home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume9 / agetty < prev    next >
Encoding:
Text File  |  1989-12-14  |  27.3 KB  |  972 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Eindhoven University of Technology, The Netherlands
  3. subject: v09i065: agetty, alternative getty for System-V
  4. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Reply-To: wietse@wzv.win.tue.nl (Wietse Z. Venema)
  6.  
  7. Posting-number: Volume 9, Issue 65
  8. Submitted-by: wietse@wzv.win.tue.nl (Wietse Z. Venema)
  9. Archive-name: agetty
  10.  
  11. This is a SYSV getty replacement that adapts itself to parity bits and
  12. to erase, kill and end-of-line characters when a user enters her login
  13. name.  It has an optional facility do detect the baud rate of incoming
  14. calls from the status messages produced by some multi-speed Hayes(tm)
  15. modem clones.
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of shell archive."
  24. # Contents:  README agetty.c agetty.8 Makefile
  25. # Wrapped by wietse@wzv on Wed Dec 13 00:22:33 1989
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'README' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'README'\"
  29. else
  30. echo shar: Extracting \"'README'\" \(490 characters\)
  31. sed "s/^X//" >'README' <<'END_OF_FILE'
  32. X@(#) README 1.1 11/26/89 22:04:59
  33. X
  34. XThis is a SYSV getty replacement that adapts itself to parity bits, and
  35. Xto erase, kill and end-of-line characters found in its input.  It also
  36. Xhas an optional facility do detect the baud rate of incoming calls from
  37. Xthe status messages produced by some multi-speed Hayes modem clones.
  38. XThis program is an adapted version of a getty I once wrote for a V7 UNIX
  39. Ximplementation; it does not use the /etc/gettydefs file.
  40. X
  41. X        Wietse Venema (wietse@wzv.win.tue.nl)
  42. END_OF_FILE
  43. if test 490 -ne `wc -c <'README'`; then
  44.     echo shar: \"'README'\" unpacked with wrong size!
  45. fi
  46. # end of 'README'
  47. fi
  48. if test -f 'agetty.c' -a "${1}" != "-c" ; then 
  49.   echo shar: Will not clobber existing file \"'agetty.c'\"
  50. else
  51. echo shar: Extracting \"'agetty.c'\" \(20261 characters\)
  52. sed "s/^X//" >'agetty.c' <<'END_OF_FILE'
  53. X/*++
  54. X/* NAME
  55. X/*    agetty 8
  56. X/* SUMMARY
  57. X/*    alternative System-V getty
  58. X/* SYNOPSIS
  59. X/*    agetty [-a alternate_rates] [-h] [-m] [-t timeout] port baud_rate
  60. X/* DESCRIPTION
  61. X/*    \fIagetty\fR opens a tty port, prompts for a login name and invokes the
  62. X/*    /bin/login command. It is normally invoked by \fIinit(8)\fR.
  63. X/*
  64. X/*    \fIagetty\fR has some useful features not present in the System
  65. X/*    V Release 2 getty command:
  66. X/* .IP o
  67. X/*    Adapts the tty settings to parity bits and to 
  68. X/*    erase, kill and end-of-line characters found in its input. The
  69. X/*    program understands 7-bit characters with even, odd, none or space
  70. X/*    parity, and 8-bit characters with no parity. The following special
  71. X/*    characters are recognized: @ and Control-U (kill); #, DEL and 
  72. X/*    backspace (erase); carriage-return and linefeed (end of line).
  73. X/* .IP o
  74. X/*    Optionally recognizes the baud rate of incoming
  75. X/*    calls from the status messages produced by some multi-speed Hayes (tm)
  76. X/*    modem clones.
  77. X/* .PP
  78. X/*    This program does not use the \fI/etc/gettydefs\fR file. Except for 
  79. X/*    differences described here the program appears to operate similar
  80. X/*    to the System-V Release 2 \fIgetty\fR program.
  81. X/*
  82. X/*    Options:
  83. X/* .TP
  84. X/* -a alternate_rates
  85. X/*    Initially the program will use the \fIbaud_rate\fR as specified.
  86. X/*    Upon receipt of successive BREAK characters the program will step
  87. X/*    through the \fIalternate_rates\fR, which should be specified as a
  88. X/*    comma-separated list (preferably in decreasing order). After all
  89. X/*    \fIalternate_rates\fR have been tried, \fIagetty\fR will try the
  90. X/*    speed specified with the \fIbaud_rate\fR argument and so on.
  91. X/* .TP
  92. X/* -h
  93. X/*    Do not hang up the line. Normally, \fIagetty\fR will lower
  94. X/*    DTR for two seconds to force a modem to hang up (if the hangup
  95. X/*    feature has been compiled into the program).
  96. X/* .TP
  97. X/* -m
  98. X/*    Try to extract the baud rate of incoming calls from the status message
  99. X/*    produced by some Hayes (tm) multi-speed modem clones. These usually
  100. X/*    produce a status message of the form: "<junk><speed><junk>".
  101. X/*    If no \fIspeed\fR is found within one second, the \fIbaud_rate\fR as
  102. X/*    specified on the command line will be used. Since this feature will
  103. X/*    work only on lightly-loaded systems, you will probably want to use this
  104. X/*    feature in combination with the \fI-a\fR option.
  105. X/* .TP
  106. X/* -t timeout
  107. X/*    Causes the program to terminate if no user name could be read
  108. X/*    within \fItimeout\fR seconds. This is useful only for dial-in lines.
  109. X/* EXAMPLES
  110. X/*    For hard-wired lines:
  111. X/* .ti +5
  112. X/*        /etc/agetty ttyM0 9600
  113. X/*
  114. X/*    For dial-in lines with a 300/1200/2400 baud Hayes clone:
  115. X/* .ti +5
  116. X/*        /etc/agetty -t60 -m -a1200,300 ttyM1 2400
  117. X/* FILES
  118. X/*    /etc/utmp, the system log file.
  119. X/* BUGS
  120. X/*    The baud-rate detection code (the \fI-m\fR option) only works if
  121. X/*    \fIagetty\fR is scheduled soon enough after completion of a dial-in 
  122. X/*    call (within 30 ms with modems that talk at 2400 baud). For robustness,
  123. X/*    always use the \fI-m\fR option in combination with the \fI-a\fR option.
  124. X/*
  125. X/*    The login prompt is always output with space parity.
  126. X/* DIAGNOSTICS
  127. X/*    All diagnostics are written to the console.
  128. X/*
  129. X/*    In particular, \fIagetty\fR will detect if it is asked to open
  130. X/*    someting that is not a terminal.
  131. X/* AUTHOR(S)
  132. X/*    W.Z. Venema 
  133. X/*    wietse@wzv.win.tue.nl
  134. X/*    Eindhoven University of Technology
  135. X/*    Department of Mathematics and Computer Science
  136. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  137. X/* CREATION DATE
  138. X/*    Sat Nov 25 22:51:05 MET 1989
  139. X/* LAST MODIFICATION
  140. X/*    89/12/11 23:02:55
  141. X/* VERSION/RELEASE
  142. X/*    1.20
  143. X/*--*/
  144. X
  145. X#ifndef lint
  146. Xstatic char sccsid[] = "@(#) agetty.c 1.20 12/11/89 23:02:55";
  147. X#endif
  148. X
  149. X#include <stdio.h>
  150. X#include <termio.h>
  151. X#include <signal.h>
  152. X#include <sys/types.h>
  153. X#include <sys/stat.h>
  154. X#include <varargs.h>
  155. X#include <ctype.h>
  156. X#include <utmp.h>
  157. X
  158. X /*
  159. X  * Things you may want to modify. HANGUP should be defined only if your tty
  160. X  * driver is not capable of hanging up the modem (by briefly dropping DTR).
  161. X  * If HANGUP is defined you probably cannot use the auto-baud and time-out
  162. X  * features.
  163. X  */
  164. X
  165. X#define LOGIN "\r\nlogin: "        /* login prompt */
  166. X
  167. X/* #define HANGUP            /* enable hangup code */
  168. X
  169. X/* Some shorthands for control characters */
  170. X
  171. X#define CTL(x)        (x ^ 0100)    /* controllify */
  172. X#define    CR        CTL('M')    /* carriage return */
  173. X#define    NL        CTL('J')    /* linefeed */
  174. X#define    BS        CTL('H')    /* backspace */
  175. X#define    DEL        CTL('?')    /* delete */
  176. X
  177. X/* Default values of special characters; you may want to change this */
  178. X
  179. X#define DEF_INTR    CTL('C')    /* default interrupt character */
  180. X#define DEF_QUIT    CTL('\\')    /* default quit character */
  181. X#define DEF_KILL    CTL('U')    /* default kill character */
  182. X#define DEF_EOF        CTL('D')    /* default EOF character */
  183. X#define DEF_SWITCH    CTL('^')    /* default switch character */
  184. X#define DEF_ERASE    BS        /* default erase character */
  185. X#define DEF_EOL        0
  186. X
  187. X/* Storage for command-line options */
  188. X
  189. X#define    MAXSPEED    10
  190. X
  191. Xstruct options {
  192. X    int     autobaud;            /* process modem status messages */
  193. X    int     timeout;            /* timeout period */
  194. X    int     hangup;            /* hang up tty */
  195. X    int     numspeed;            /* number of baud rates to try */
  196. X    int     curspeed;            /* current speed */
  197. X    int     speeds[MAXSPEED];        /* baud rates to be tried */
  198. X    char   *tty;            /* name of tty */
  199. X};
  200. X
  201. X/* Storage for things detected while the login name was read */
  202. X
  203. Xstruct chardata {
  204. X    int     erase;            /* erase character */
  205. X    int     kill;            /* kill character */
  206. X    int     eol;            /* end-of-line character */
  207. X    int     parity;            /* what parity did we see */
  208. X    int     capslock;            /* upper case without lower case */
  209. X};
  210. X
  211. X/* The following is used for understandable diagnostics */
  212. X
  213. Xextern int errno;
  214. Xextern char *sys_errlist[];
  215. Xstatic char *progname;
  216. Xextern char *strcpy();
  217. Xextern char *strcat();
  218. X
  219. X/* ... */
  220. X
  221. Xmain(argc, argv)
  222. Xint     argc;
  223. Xchar  **argv;
  224. X{
  225. X    char   *logname;            /* login name, given to /bin/login */
  226. X    char   *get_logname();
  227. X    struct chardata chardata;        /* set by get_logname() */
  228. X    struct termio termio;        /* terminal mode bits */
  229. X    static struct options options = {
  230. X    0,                /* no modem status message processing */
  231. X    0,                /* no timeout */
  232. X    1,                /* do hangup */
  233. X    1,                /* no baud-rate cycling */
  234. X    0,                /* use baud-rate argument as speed */
  235. X    };
  236. X
  237. X    progname = argv[0];
  238. X
  239. X    /* Parse command-line arguments */
  240. X
  241. X    parse_args(argc, argv, &options);
  242. X
  243. X    /* Update the utmp file */
  244. X
  245. X    update_utmp(options.tty);
  246. X
  247. X    /* Open the tty as standard { input, output, error } */
  248. X
  249. X    open_tty(options.tty, &termio);
  250. X
  251. X    /* Optionally hang up the tty */
  252. X
  253. X    if (options.hangup)
  254. X    hangup_tty(&termio);
  255. X
  256. X    /* Initialize the termio settings (raw mode, eight-bit, blocking i/o) */
  257. X
  258. X    termio_init(&termio, options.speeds[0]);
  259. X
  260. X    /* Optionally detect the baud rate from the modem status message */
  261. X
  262. X    if (options.autobaud)
  263. X    auto_baud(&termio);
  264. X
  265. X    /* With dial-in lines, briefly pause to allow modems etc. to settle */
  266. X
  267. X    if (options.timeout)
  268. X    (void) sleep(1);
  269. X
  270. X    /* Optional time-out feature */
  271. X
  272. X    if (options.timeout)
  273. X    (void) alarm((unsigned) options.timeout);
  274. X
  275. X    /* Read the login name */
  276. X
  277. X    while ((logname = get_logname(&options, &chardata)) == 0)
  278. X    next_speed(&termio, &options);
  279. X
  280. X    /* Disable time-out feature */
  281. X
  282. X    if (options.timeout)
  283. X    (void) alarm(0);
  284. X
  285. X    /* Finalize the termio settings */
  286. X
  287. X    termio_final(&termio, &chardata);
  288. X
  289. X    /* Now the newline should be properly output */
  290. X
  291. X    (void) write(1, "\n", 1);
  292. X
  293. X    /* Let /bin/login take care of password validation */
  294. X
  295. X    execl("/bin/login", "login", logname, (char *) 0);
  296. X    error("%s: can't exec /bin/login", options.tty);
  297. X    /* NOTREACHED */
  298. X}
  299. X
  300. X/* parse-args - parse command-line arguments */
  301. X
  302. Xparse_args(argc, argv, op)
  303. Xint     argc;
  304. Xchar  **argv;
  305. Xstruct options *op;
  306. X{
  307. X    extern char *optarg;        /* getopt */
  308. X    extern int optind;            /* getopt */
  309. X    int     c;
  310. X
  311. X    while ((c = getopt(argc, argv, "a:hmt:")) != EOF) {
  312. X    switch (c) {
  313. X    case 'a':                /* enable auto-baud feature */
  314. X        parse_speeds(op, optarg);
  315. X        break;
  316. X    case 'h':                /* do not hangup the tty */
  317. X        op->hangup = 0;
  318. X        break;
  319. X    case 'm':                /* parse modem status message */
  320. X        op->autobaud = 1;
  321. X        break;
  322. X    case 't':                /* time out */
  323. X        if ((op->timeout = atoi(optarg)) <= 0)
  324. X        error("bad timeout value: %s", optarg);
  325. X        break;
  326. X    case '?':
  327. X        usage();
  328. X    }
  329. X    }
  330. X    if (argc != optind + 2)            /* check parameter count */
  331. X    usage();
  332. X    op->tty = argv[optind++];            /* tty name */
  333. X    if ((op->speeds[0] = bcode(argv[optind])) <= 0)    /* baud rate */
  334. X    error("bad speed: %s", argv[optind]);
  335. X}
  336. X
  337. X/* parse_speeds - parse alternate baud rates */
  338. X
  339. Xparse_speeds(op, arg)
  340. Xstruct options *op;
  341. Xchar   *arg;
  342. X{
  343. X    char   *strtok();
  344. X    char   *cp;
  345. X
  346. X    for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) {
  347. X    if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
  348. X        error("bad speed: %s", cp);
  349. X    if (op->numspeed > MAXSPEED)
  350. X        error("too many alternate speeds");
  351. X    }
  352. X}
  353. X
  354. X/* update_utmp - update our utmp entry */
  355. X
  356. Xupdate_utmp(line)
  357. Xchar   *line;
  358. X{
  359. X    struct utmp ut;
  360. X    long    ut_size = sizeof(ut);    /* avoid nonsense */
  361. X    int     ut_fd;
  362. X    int     mypid = getpid();
  363. X    long    time();
  364. X    long    lseek();
  365. X
  366. X    /*
  367. X     * The utmp file holds miscellaneous information about things started by
  368. X     * /etc/init and other system-related events. Our purpose is to update
  369. X     * the utmp entry for the current process, in particular the process type
  370. X     * and the tty line we are listening to. Return successfully only if the
  371. X     * utmp file can be opened for update, and if we are able to find our
  372. X     * entry in the utmp file.
  373. X     */
  374. X
  375. X    if ((ut_fd = open(UTMP_FILE, 2)) < 0) {
  376. X    error("%s: open for update", UTMP_FILE);
  377. X    } else {
  378. X    while (read(ut_fd, (char *) &ut, sizeof(ut)) == sizeof(ut)) {
  379. X        if (ut.ut_type == INIT_PROCESS && ut.ut_pid == mypid) {
  380. X        ut.ut_type = LOGIN_PROCESS;
  381. X        ut.ut_time = time((long *) 0);
  382. X        (void) strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name));
  383. X        (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
  384. X        (void) lseek(ut_fd, -ut_size, 1);
  385. X        (void) write(ut_fd, (char *) &ut, sizeof(ut));
  386. X        (void) close(ut_fd);
  387. X        return;
  388. X        }
  389. X    }
  390. X    error("no utmp entry found for process id %u", mypid);
  391. X    }
  392. X}
  393. X
  394. X/* open_tty - open tty as standard { input, output, error } */
  395. X
  396. Xopen_tty(tty, tp)
  397. Xchar   *tty;
  398. Xstruct termio *tp;
  399. X{
  400. X    struct stat st;
  401. X
  402. X    /* Close standard { input, output, error } files, just in case */
  403. X
  404. X    (void) close(0);
  405. X    (void) close(1);
  406. X    (void) close(2);
  407. X    errno = 0;                    /* ignore above errors */
  408. X
  409. X    /* Make sure we are given a character device */
  410. X
  411. X    if (chdir("/dev"))
  412. X    error("/dev: chdir() failed");
  413. X    if (stat(tty, &st) < 0)
  414. X    error("/dev/%s: stat() failed", tty);
  415. X    if ((st.st_mode & S_IFMT) != S_IFCHR)
  416. X    error("not a character device: /dev/%s", tty);
  417. X
  418. X    /* Set up new standard input, output and error files */
  419. X
  420. X    if (open(tty, 2) != 0)            /* set up std input */
  421. X    error("/dev/%s: cannot open as standard input", tty);
  422. X    if (dup(0) != 1 || dup(0) != 2)        /* set up std out and std err */
  423. X    error("%s: dup problem", tty);        /* we have a problem */
  424. X    if (ioctl(0, TCGETA, tp) < 0)        /* read tty status bits */
  425. X    error("%s: ioctl failed", tty);        /* this is not a terminal */
  426. X
  427. X    /* It seems to be a terminal; set proper protections and ownership */
  428. X
  429. X    (void) chown(tty, 0, 0);            /* root, sys */
  430. X    (void) chmod(tty, 0622);            /* crw--w--w- */
  431. X    errno = 0;                    /* ignore above errors */
  432. X}
  433. X
  434. X/* hangup_tty - hang up by forcing DTR down for at least 2 seconds */
  435. X
  436. Xhangup_tty(tp)
  437. Xstruct termio *tp;
  438. X{
  439. X#ifdef    HANGUP
  440. X    (void) signal(SIGHUP, SIG_IGN);
  441. X    tp->c_cflag &= ~CBAUD;
  442. X    tp->c_cflag |= B0;
  443. X    (void) ioctl(0, TCSETA, tp);
  444. X    (void) signal(SIGHUP, SIG_DFL);
  445. X    (void) sleep(2);
  446. X#endif
  447. X}
  448. X
  449. X/* termio_init - initialize termio settings */
  450. X
  451. Xtermio_init(tp, speed)
  452. Xstruct termio *tp;
  453. Xint speed;
  454. X{
  455. X
  456. X    /*
  457. X     * Initial termio settings: 8-bit characters, raw-mode, blocking i/o.
  458. X     * Special characters are set after we have read the login name; all
  459. X     * reads will be done in raw mode anyway.
  460. X     */
  461. X
  462. X    tp->c_cflag = CS8 | HUPCL | CREAD | speed;
  463. X    tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0;
  464. X    tp->c_cc[VMIN] = 1;
  465. X    tp->c_cc[VTIME] = 0;
  466. X    (void) ioctl(0, TCSETA, tp);
  467. X}
  468. X
  469. X/* auto_baud - extract baud rate from modem status message */
  470. X
  471. Xauto_baud(tp)
  472. Xstruct termio *tp;
  473. X{
  474. X    int     speed;
  475. X    int     vmin;
  476. X    int     iflag;
  477. X    char    buf[BUFSIZ];
  478. X    char   *bp;
  479. X    int     nread;
  480. X
  481. X    /*
  482. X     * This works only if the modem produces its status code AFTER raising
  483. X     * the DCD line, and if the computer is fast enough to set the proper
  484. X     * baud rate before the message has gone by. We expect a message of the
  485. X     * following format:
  486. X     * 
  487. X     * <junk><number><junk>
  488. X     * 
  489. X     * The number is interpreted as the baud rate of the incoming call. If the
  490. X     * modem does not tell us the baud rate within one second we will keep
  491. X     * using the current baud rate. It is advisable to enable baud-rate
  492. X     * cycling (-a option) if the processing of modem status messages is
  493. X     * enabled.
  494. X     */
  495. X
  496. X    /* Use 7-bit characters, don't block if input queue is empty */
  497. X
  498. X    iflag = tp->c_iflag;
  499. X    tp->c_iflag |= ISTRIP;            /* enable 8th-bit stripping */
  500. X    vmin = tp->c_cc[VMIN];
  501. X    tp->c_cc[VMIN] = 0;                /* don't block if queue empty */
  502. X    (void) ioctl(0, TCSETA, tp);
  503. X
  504. X    /*
  505. X     * Wait for a while, then read everything the modem has said so far and
  506. X     * try to extract the speed of the dial-in call.
  507. X     */
  508. X
  509. X    (void) sleep(1);
  510. X    if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) {
  511. X    buf[nread] = '\0';
  512. X    for (bp = buf; bp < buf + nread; bp++) {
  513. X        if (isascii(*bp) && isdigit(*bp)) {
  514. X        if (speed = bcode(bp)) {
  515. X            tp->c_cflag &= ~CBAUD;
  516. X            tp->c_cflag |= speed;
  517. X        }
  518. X        break;
  519. X        }
  520. X    }
  521. X    }
  522. X    /* Restore settings */
  523. X
  524. X    tp->c_iflag = iflag;
  525. X    tp->c_cc[VMIN] = vmin;
  526. X    (void) ioctl(0, TCSETA, tp);
  527. X}
  528. X
  529. X/* next_speed - select next baud rate */
  530. X
  531. Xnext_speed(tp, op)
  532. Xstruct termio *tp;
  533. Xstruct options *op;
  534. X{
  535. X    op->curspeed = (op->curspeed + 1) % op->numspeed;
  536. X    tp->c_cflag &= ~CBAUD;
  537. X    tp->c_cflag |= op->speeds[op->curspeed];
  538. X    (void) ioctl(0, TCSETA, tp);
  539. X}
  540. X
  541. X/* get_logname - get user name, establish parity, speed, erase, kill, eol */
  542. X
  543. Xchar   *get_logname(op, cp)
  544. Xstruct options *op;
  545. Xstruct chardata *cp;
  546. X{
  547. X    char    logname[BUFSIZ];
  548. X    char   *bp;
  549. X    char    c;                /* input character, full eight bits */
  550. X    char    ascval;            /* low 7 bits of input character */
  551. X    int     bits;            /* # of "1" bits per character */
  552. X    int     mask;            /* mask with 1 bit up */
  553. X    static char *erase[] = {        /* backspace-space-backspace */
  554. X    "\010\040\010",            /* space parity */
  555. X    "\010\040\010",            /* odd parity */
  556. X    "\210\240\210",            /* even parity */
  557. X    "\210\240\210",            /* no parity */
  558. X    };
  559. X
  560. X    /* Initialize kill, erase, parity etcetera (also after switching speeds) */
  561. X
  562. X    cp->kill = DEF_KILL;
  563. X    cp->erase = DEF_ERASE;
  564. X    cp->parity = 0;
  565. X
  566. X    /* Flush any pending input */
  567. X
  568. X    ioctl(0, TCFLSH, (struct termio *) 0);
  569. X
  570. X    /* Read a login name */
  571. X
  572. X    for (*logname = 0; *logname == 0; /* void */ ) {
  573. X
  574. X    /* Write the prompt, with "parity" bit == 0 */
  575. X
  576. X    (void) write(1, LOGIN, sizeof(LOGIN) - 1);
  577. X
  578. X    /* Read name, watch for break, parity, erase, kill, end-of-line */
  579. X
  580. X    for (bp = logname, cp->eol = 0; cp->eol == 0; /* void */ ) {
  581. X        if (read(0, &c, 1) < 1)
  582. X        error("%s: read error", op->tty);
  583. X
  584. X        /* Do BREAK handling elsewhere */
  585. X
  586. X        if ((c == 0) && op->numspeed > 1)
  587. X        return (0);
  588. X
  589. X        /* Do parity bit handling */
  590. X
  591. X        if (c != (ascval = (c & 0177))) {    /* "parity" bit on ? */
  592. X        for (bits = 1, mask = 1; mask & 0177; mask <<= 1)
  593. X            if (mask & ascval)
  594. X            bits++;            /* count "1" bits */
  595. X        cp->parity |= ((bits & 1) ? 1 : 2);
  596. X        }
  597. X        /* Do erase, kill and end-of-line processing */
  598. X
  599. X        switch (ascval) {
  600. X        case CR:
  601. X        case NL:
  602. X        *bp = 0;            /* terminate logname */
  603. X        cp->eol = ascval;        /* send end-of-line char */
  604. X        break;
  605. X        case BS:
  606. X        case DEL:
  607. X        case '#':
  608. X        cp->erase = ascval;        /* set erase character */
  609. X        if (bp > logname) {
  610. X            (void) write(1, erase[cp->parity], 3);
  611. X            bp--;
  612. X        }
  613. X        break;
  614. X        case CTL('U'):
  615. X        case '@':
  616. X        cp->kill = ascval;        /* set kill character */
  617. X        while (bp > logname) {
  618. X            (void) write(1, erase[cp->parity], 3);
  619. X            bp--;
  620. X        }
  621. X        break;
  622. X        case CTL('D'):
  623. X        exit(0);
  624. X        default:
  625. X        if (!isascii(ascval) || !isprint(ascval)) {
  626. X             /* ignore garbage characters */ ;
  627. X        } else if (bp - logname >= sizeof(logname) - 1) {
  628. X            error("%s: input overrun", op->tty);
  629. X        } else {
  630. X            (void) write(1, &c, 1);    /* echo the character */
  631. X            *bp++ = ascval;        /* and store it */
  632. X        }
  633. X        break;
  634. X        }
  635. X    }
  636. X    }
  637. X    cp->capslock = caps_lock(logname);        /* upper case w/o lower case? */
  638. X    return (logname);
  639. X}
  640. X
  641. X/* termio_final - set the final tty mode bits */
  642. X
  643. Xtermio_final(tp, cp)
  644. Xstruct termio *tp;
  645. Xstruct chardata *cp;
  646. X{
  647. X    /* General terminal-independent stuff */
  648. X
  649. X    tp->c_iflag |= IXON | IXOFF;        /* 2-way flow control */
  650. X    tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK;
  651. X    tp->c_oflag |= OPOST;
  652. X    tp->c_cc[VEOF] = DEF_EOF;
  653. X    tp->c_cc[VEOL] = DEF_EOL;
  654. X    tp->c_cc[VINTR] = DEF_INTR;
  655. X    tp->c_cc[VQUIT] = DEF_QUIT;
  656. X    tp->c_cc[VKILL] = DEF_KILL;
  657. X    tp->c_cc[VERASE] = DEF_ERASE;
  658. X    tp->c_cc[VSWTCH] = DEF_SWITCH;
  659. X
  660. X    /* Account for special characters seen in input */
  661. X
  662. X    if (cp->eol == CR) {
  663. X    tp->c_iflag |= ICRNL;            /* map CR in input to NL */
  664. X    tp->c_oflag |= ONLCR;            /* map NL in output to CR-NL */
  665. X    }
  666. X    tp->c_cc[VERASE] = cp->erase;        /* set erase character */
  667. X    tp->c_cc[VKILL] = cp->kill;            /* set kill character */
  668. X
  669. X    /* Account for the presence or absence of parity bits in input */
  670. X
  671. X    switch (cp->parity) {
  672. X    case 0:                    /* space (always 0) parity */
  673. X    break;
  674. X    case 1:                    /* odd parity */
  675. X    tp->c_cflag |= PARODD;
  676. X    /* FALLTHROUGH */
  677. X    case 2:                    /* even parity */
  678. X    tp->c_cflag |= PARENB;
  679. X    tp->c_iflag |= INPCK | ISTRIP;
  680. X    /* FALLTHROUGH */
  681. X    case (1 | 2):                /* no parity bit */
  682. X    tp->c_cflag &= ~CSIZE;
  683. X    tp->c_cflag |= CS7;
  684. X    break;
  685. X    }
  686. X    /* Account for upper case without lower case */
  687. X
  688. X    if (cp->capslock) {
  689. X    tp->c_iflag |= IUCLC;
  690. X    tp->c_lflag |= XCASE;
  691. X    tp->c_oflag |= OLCUC;
  692. X    }
  693. X
  694. X    /* Finally, make the new settings effective */
  695. X
  696. X    (void) ioctl(0, TCSETA, tp);
  697. X}
  698. X
  699. X/* caps_lock - string contains upper case without lower case */
  700. X
  701. Xcaps_lock(s)
  702. Xchar   *s;
  703. X{
  704. X    int     hascaps;
  705. X
  706. X    for (hascaps = 0; *s; s++) {
  707. X    if (islower(*s))
  708. X        return (0);
  709. X    if (hascaps == 0)
  710. X        hascaps = isupper(*s);
  711. X    }
  712. X    return (hascaps);
  713. X}
  714. X
  715. X/* bcode - convert speed string to speed code; return 0 on failure */
  716. X
  717. Xbcode(s)
  718. Xchar   *s;
  719. X{
  720. X    struct Speedtab {
  721. X    int     speed;
  722. X    int     code;
  723. X    };
  724. X    static struct Speedtab speedtab[] = {
  725. X    50, B50,
  726. X    75, B75,
  727. X    110, B110,
  728. X    134, B134,
  729. X    150, B150,
  730. X    200, B200,
  731. X    300, B300,
  732. X    600, B600,
  733. X    1200, B1200,
  734. X    1800, B1800,
  735. X    2400, B2400,
  736. X    4800, B4800,
  737. X    9600, B9600,
  738. X    19200, EXTA,
  739. X    0, 0,
  740. X    };
  741. X    struct Speedtab *sp;
  742. X    int     speed = atoi(s);
  743. X
  744. X    for (sp = speedtab; sp->speed; sp++)
  745. X    if (sp->speed == speed)
  746. X        return (sp->code);
  747. X    return (0);
  748. X}
  749. X
  750. X/* usage - explain */
  751. X
  752. Xusage()
  753. X{
  754. X    error("usage: %s [-a alternate_rates] [-h] [-m] [-t timeout] line baud_rate",
  755. X      progname);
  756. X}
  757. X
  758. X/* error - report errors to the console; only understands %s */
  759. X
  760. X#define    str2cpy(b,s1,s2)    strcat(strcpy(b,s1),s2)
  761. X
  762. X/* VARARGS */
  763. X
  764. Xerror(va_alist)
  765. Xva_dcl
  766. X{
  767. X    va_list ap;
  768. X    char   *fmt;
  769. X    int     fd;
  770. X    int     err = errno;
  771. X    char    buf[BUFSIZ];
  772. X    char   *bp;
  773. X
  774. X    if ((fd = open("/dev/console", 1)) >= 0) {
  775. X    (void) str2cpy(buf, progname, ": ");
  776. X    bp = buf + strlen(buf);
  777. X
  778. X    /*
  779. X     * %s expansion is done by hand. The program would become three times
  780. X     * as big if we would use the stdio library...
  781. X     */
  782. X
  783. X    va_start(ap);
  784. X    fmt = va_arg(ap, char *);
  785. X    while (*fmt) {
  786. X        if (strncmp(fmt, "%s", 2) == 0) {
  787. X        (void) strcat(bp, va_arg(ap, char *));
  788. X        bp += strlen(bp);
  789. X        fmt += 2;
  790. X        } else {
  791. X        *bp++ = *fmt++;
  792. X        }
  793. X    }
  794. X    *bp = 0;
  795. X    va_end(ap);
  796. X
  797. X    /* Add system error message if errno was set */
  798. X
  799. X    if (err)
  800. X        (void) str2cpy(bp, ": ", sys_errlist[errno]);
  801. X
  802. X    /* Terminate with CR-LF since the console mode is unknown */
  803. X
  804. X    (void) strcat(bp, "\r\n");
  805. X    (void) write(fd, buf, strlen(buf));
  806. X    (void) close(fd);
  807. X    }
  808. X    (void) sleep(5);                /* be kind to init */
  809. X    exit(1);
  810. X}
  811. X
  812. END_OF_FILE
  813. if test 20261 -ne `wc -c <'agetty.c'`; then
  814.     echo shar: \"'agetty.c'\" unpacked with wrong size!
  815. fi
  816. # end of 'agetty.c'
  817. fi
  818. if test -f 'agetty.8' -a "${1}" != "-c" ; then 
  819.   echo shar: Will not clobber existing file \"'agetty.8'\"
  820. else
  821. echo shar: Extracting \"'agetty.8'\" \(3388 characters\)
  822. sed "s/^X//" >'agetty.8' <<'END_OF_FILE'
  823. X.TH AGETTY 8 
  824. X.ad
  825. X.fi
  826. X.SH NAME
  827. Xagetty
  828. X\-
  829. Xalternative System-V getty
  830. X.SH SYNOPSIS
  831. X.na
  832. X.nf
  833. Xagetty [-a alternate_rates] [-h] [-m] [-t timeout] port baud_rate
  834. X.SH DESCRIPTION
  835. X.ad
  836. X.fi
  837. X\fIagetty\fR opens a tty port, prompts for a login name and invokes the
  838. X/bin/login command. It is normally invoked by \fIinit(8)\fR.
  839. X
  840. X\fIagetty\fR has some useful features not present in the System
  841. XV Release 2 getty command:
  842. X.IP o
  843. XAdapts the tty settings to parity bits and to
  844. Xerase, kill and end-of-line characters found in its input. The
  845. Xprogram understands 7-bit characters with even, odd, none or space
  846. Xparity, and 8-bit characters with no parity. The following special
  847. Xcharacters are recognized: @ and Control-U (kill); #, DEL and
  848. Xbackspace (erase); carriage-return and linefeed (end of line).
  849. X.IP o
  850. XOptionally recognizes the baud rate of incoming
  851. Xcalls from the status messages produced by some multi-speed Hayes (tm)
  852. Xmodem clones.
  853. X.PP
  854. XThis program does not use the \fI/etc/gettydefs\fR file. Except for
  855. Xdifferences described here the program appears to operate similar
  856. Xto the System-V Release 2 \fIgetty\fR program.
  857. X
  858. XOptions:
  859. X.TP
  860. X-a alternate_rates
  861. XInitially the program will use the \fIbaud_rate\fR as specified.
  862. XUpon receipt of successive BREAK characters the program will step
  863. Xthrough the \fIalternate_rates\fR, which should be specified as a
  864. Xcomma-separated list (preferably in decreasing order). After all
  865. X\fIalternate_rates\fR have been tried, \fIagetty\fR will try the
  866. Xspeed specified with the \fIbaud_rate\fR argument and so on.
  867. X.TP
  868. X-h
  869. XDo not hang up the line. Normally, \fIagetty\fR will lower
  870. XDTR for two seconds to force a modem to hang up (if the hangup
  871. Xfeature has been compiled into the program).
  872. X.TP
  873. X-m
  874. XTry to extract the baud rate of incoming calls from the status message
  875. Xproduced by some Hayes (tm) multi-speed modem clones. These usually
  876. Xproduce a status message of the form: "<junk><speed><junk>".
  877. XIf no \fIspeed\fR is found within one second, the \fIbaud_rate\fR as
  878. Xspecified on the command line will be used. Since this feature will
  879. Xwork only on lightly-loaded systems, you will probably want to use this
  880. Xfeature in combination with the \fI-a\fR option.
  881. X.TP
  882. X-t timeout
  883. XCauses the program to terminate if no user name could be read
  884. Xwithin \fItimeout\fR seconds. This is useful only for dial-in lines.
  885. X.SH EXAMPLES
  886. X.na
  887. X.nf
  888. XFor hard-wired lines:
  889. X.ti +5
  890. X/etc/agetty ttyM0 9600
  891. X
  892. XFor dial-in lines with a 300/1200/2400 baud Hayes clone:
  893. X.ti +5
  894. X/etc/agetty -t60 -m -a1200,300 ttyM1 2400
  895. X.SH FILES
  896. X.na
  897. X.nf
  898. X/etc/utmp, the system log file.
  899. X.SH BUGS
  900. X.ad
  901. X.fi
  902. XThe baud-rate detection code (the \fI-m\fR option) only works if
  903. X\fIagetty\fR is scheduled soon enough after completion of a dial-in
  904. Xcall (within 30 ms with modems that talk at 2400 baud). For robustness,
  905. Xalways use the \fI-m\fR option in combination with the \fI-a\fR option.
  906. X
  907. XThe login prompt is always output with space parity.
  908. X.SH DIAGNOSTICS
  909. X.ad
  910. X.fi
  911. XAll diagnostics are written to the console.
  912. X
  913. XIn particular, \fIagetty\fR will detect if it is asked to open
  914. Xsometing that is not a terminal.
  915. X.SH AUTHOR(S)
  916. X.na
  917. X.nf
  918. XW.Z. Venema
  919. Xwietse@wzv.win.tue.nl
  920. XEindhoven University of Technology
  921. XDepartment of Mathematics and Computer Science
  922. XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  923. X.SH CREATION DATE
  924. X.na
  925. X.nf
  926. XSat Nov 25 22:51:05 MET 1989
  927. X.SH LAST MODIFICATION
  928. X.na
  929. X.nf
  930. X89/12/11 23:02:55
  931. X.SH VERSION/RELEASE
  932. X.na
  933. X.nf
  934. X1.20
  935. END_OF_FILE
  936. if test 3388 -ne `wc -c <'agetty.8'`; then
  937.     echo shar: \"'agetty.8'\" unpacked with wrong size!
  938. fi
  939. # end of 'agetty.8'
  940. fi
  941. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  942.   echo shar: Will not clobber existing file \"'Makefile'\"
  943. else
  944. echo shar: Extracting \"'Makefile'\" \(257 characters\)
  945. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  946. X# @(#) Makefile 1.3 11/26/89 22:20:28 
  947. X
  948. XSHELL    = /bin/sh
  949. XCFLAGS    = -s -O
  950. XFILES    = README agetty.c agetty.8 Makefile
  951. X
  952. Xagetty: agetty.c
  953. X    cc $(CFLAGS) -o $@ $?
  954. X
  955. Xclean:
  956. X    rm -f agetty.o agetty
  957. X
  958. Xshar:    $(FILES)
  959. X    @shar $(FILES)
  960. X
  961. Xagetty.8:
  962. X    srctoman agetty.c >agetty.8
  963. END_OF_FILE
  964. if test 257 -ne `wc -c <'Makefile'`; then
  965.     echo shar: \"'Makefile'\" unpacked with wrong size!
  966. fi
  967. # end of 'Makefile'
  968. fi
  969. echo shar: End of shell archive.
  970. exit 0
  971.  
  972.